#include "Sphere.h"
#include "FuriousTourist.h"

Sphere::Sphere(float radius, ObjectMaterial material, ObjectType objectType)
{
	mShowHealth = false;

	mObjectType = objectType;
	body = new physics::RigidBody;
	mHealth = 100;

	mMaterial = material;

	mMulti1 = NULL;
	mMulti2 = NULL;
	mMulti3 = NULL;

	mSetToRed = false;

	CollisionSphere::radius = (physics::real)radius;

	physics::real mass = 4.0f*0.3333f*3.1415f * radius*radius*radius * GetDensity(material);
    body->setMass(mass);

    physics::Matrix3 tensor;
    physics::real coeff = 0.4f*mass*radius*radius;
    tensor.setInertiaTensorCoeffs(coeff,coeff,coeff);
    body->setInertiaTensor(tensor);

	body->setDamping(0.9, 0.4);
	body->setAwake();
	body->SetMaterial(mMaterial);

	//char* meshFile;
	float scale = 1.0f;

	switch(mObjectType)
	{
	case WEAPONTYPE_NORMAL:
		scale = COCONUT_SCALE;
		break;
	case WEAPONTYPE_MULTI:
		scale = MULTINUT_SCALE;
		mMulti1 = new Sphere(radius*COMPONENTNUT_FACTOR, OBJECTMATERIAL_DEFAULT, WEAPONTYPE_NORMAL);
		mMulti2 = new Sphere(radius*COMPONENTNUT_FACTOR, OBJECTMATERIAL_DEFAULT, WEAPONTYPE_NORMAL);
		mMulti3 = new Sphere(radius*COMPONENTNUT_FACTOR, OBJECTMATERIAL_DEFAULT, WEAPONTYPE_NORMAL);
		break;
	case WEAPONTYPE_ROCKET:
		scale = ROCKETNUT_SCALE;
		break;
	case WEAPONTYPE_EXPLODE:
		scale = EXPLODENUT_SCALE;
		break;
	case BIRDTYPE_BLACKBIRD:
		scale = BLACKBIRD_SCALE;
		break;
	case BIRDTYPE_SEAGULL:
		scale = SEAGULL_SCALE;
		break;
	case BIRDTYPE_PARROT:
		scale = PARROT_SCALE;
		break;
	case BIRDTYPE_TOUCAN:
		scale = TOUCAN_SCALE;
		break;
	case OBJECTTYPE_CATAPULT:
		scale = CATAPULT_SCALE;
		break;

	case OBJECTTYPE_STONESPHERE:
		scale = radius;
		break;

	default:
		scale = COCONUT_SCALE;
	}

	scale *= radius / SPHERE_DEFAULTRADIUS;

	D3DXMatrixScaling(&mScale, scale, scale, scale);

	mMtrl = Mtrl(WHITE*0.8f, WHITE, WHITE*0.8f, 8.0f);
	
}


Sphere::~Sphere(void)
{
	if (mMulti1 != NULL)
		delete mMulti1;

	if (mMulti2 != NULL)
		delete mMulti2;

	if (mMulti3 != NULL)
		delete mMulti3;

	delete body;
}

void Sphere::Render(RenderInfo ri)
{
	MeshData* meshData = MESHMANAGER->GetMesh(mObjectType);

	gD3DDevice->SetRenderState(D3DRS_WRAP0, D3DWRAP_U);

	D3DXMATRIX W, WIT;

	W = mScale * body->getDXTransform();

	D3DXMatrixInverse(&WIT, 0, &W);
	D3DXMatrixTranspose(&WIT, &WIT);

	ri.mFX->SetMatrix(ri.mhWVP, &(W * ri.mView * ri.mProj));
	ri.mFX->SetMatrix(ri.mhWorld, &W);
	ri.mFX->SetMatrix(ri.mhWorldInvTrans, &WIT);

#ifdef _SHOWSTATECOLORS
	if (!body->getActivated())
	{
		Mtrl mtrl = Mtrl(RED, RED, RED, 1.0f);
		ri.mFX->SetValue(ri.mhAmbientMtrl, &mtrl.ambient, sizeof(D3DXCOLOR));
	}
	else if (!body->getAwake())
	{
		Mtrl mtrl = Mtrl(BLUE, BLUE, BLUE, 1.0f);
		ri.mFX->SetValue(ri.mhAmbientMtrl, &mtrl.ambient, sizeof(D3DXCOLOR));
	}
	else
	{
		if (mSetToRed)
		{
			Mtrl mtrl = Mtrl(RED, RED, RED, 1.0f);
			ri.mFX->SetValue(ri.mhAmbientMtrl, &mtrl.ambient, sizeof(D3DXCOLOR));
		}
		else
			ri.mFX->SetValue(ri.mhAmbientMtrl, &mMtrl.ambient, sizeof(D3DXCOLOR));
	}
#else
	if (mSetToRed)
	{
		Mtrl mtrl = Mtrl(RED, RED, RED, 1.0f);
		ri.mFX->SetValue(ri.mhAmbientMtrl, &mtrl.ambient, sizeof(D3DXCOLOR));
	}
	else
		ri.mFX->SetValue(ri.mhAmbientMtrl, &mMtrl.ambient, sizeof(D3DXCOLOR));
#endif

	if (mShowHealth)
	{
		int r = (100 - mHealth) * 2.5;
		int g = 250 - ((100 - mHealth) * 2.5);
		
		D3DCOLOR color = D3DCOLOR_XRGB(r, g, 0);
		Mtrl mtrl = Mtrl(color, color, color, 1.0f);
		ri.mFX->SetValue(ri.mhAmbientMtrl, &mtrl.ambient, sizeof(D3DXCOLOR));
	}
	else
	{
		ri.mFX->SetValue(ri.mhSpecMtrl, &mMtrl.spec, sizeof(D3DXCOLOR));
		ri.mFX->SetFloat(ri.mhSpecPower, mMtrl.specPower);
	}

	for (UINT j = 0; j < meshData->materialList->size(); ++j)
	{
		
		ri.mFX->SetValue(ri.mhDiffuseMtrl, &meshData->materialList->operator[](j).ambient, sizeof(Mtrl));
		
		if (meshData->textureList->operator[](j) != 0)
			ri.mFX->SetTexture(ri.mhTex, meshData->textureList->operator[](j));

		ri.mFX->CommitChanges();

		meshData->mesh->DrawSubset(j);
	}

	gD3DDevice->SetRenderState(D3DRS_WRAP0, 0);
}

void Sphere::SpecialAbility(FuriousTourist *game)
{
	physics::Vector3 v, p;
	physics::Quaternion q;
	physics::Matrix3 m;
	GameObject* pGameObject;
	CollisionPrimitive* pPrimitive;
	switch(mObjectType)
	{
	case WEAPONTYPE_NORMAL:
		// do nothing
		break;

	case WEAPONTYPE_MULTI:
		// create a nut that shoots up
		body->getPosition(&p);
		body->getVelocity(&v);
		q = physics::Quaternion(1, 0, 0, -0.1);
		q.normalize();
		m.setOrientation(q);
		v = m * v;
		mMulti1->body->setPosition(p);
		mMulti1->body->setVelocity(v);
		mMulti1->body->setOrientation(body->getOrientation());
		pGameObject = mMulti1;
		pGameObject->HasHealth();
		pPrimitive = mMulti1;
		game->CreateAsset(pPrimitive, pGameObject);
		
		// create a nut that follows the original trajectory
		body->getVelocity(&v);
		mMulti2->body->setPosition(p);
		mMulti2->body->setVelocity(v);
		mMulti2->body->setOrientation(body->getOrientation());
		pGameObject = mMulti2;
		pPrimitive = mMulti2;
		game->CreateAsset(pPrimitive, pGameObject);
		
		// create a nut that shoots down
		q = physics::Quaternion(1, 0, 0, 0.1);
		q.normalize();
		m.setOrientation(q);
		v = m*v;
		mMulti3->body->setPosition(p);
		mMulti3->body->setVelocity(v);
		mMulti3->body->setOrientation(body->getOrientation());
		pGameObject = mMulti3;
		pPrimitive = mMulti3;
		game->CreateAsset(pPrimitive, pGameObject);
		
		
		// set the projectile to something valid
		pGameObject = mMulti2;
		game->SetProjectile(pGameObject);
		game->ClearFirstWeapon();

		// clear these pointers so we don't delete the
		// sub-nuts when we're about to call this nut's constructor
		mMulti1 = NULL;
		mMulti2 = NULL;
		mMulti3 = NULL;

		SOUNDMANAGER->SoundPlay(SOUND_MULTINUTSPLIT);

		// destroy this coconut
		game->DestroyAsset(body);
		break;

	case WEAPONTYPE_ROCKET:
		body->getVelocity(&v);
		v.normalize();
		v *= ROCKETNUT_VELOCITYFACTOR;
		body->setVelocity(v);
		SOUNDMANAGER->SoundPlay(SOUND_ROCKETNUTLAUNCH);
		break;

	case WEAPONTYPE_EXPLODE:
		body->getPosition(&p);
		game->GenerateExplosion(p);
		game->SetProjectile(NULL);
		game->ClearFirstWeapon();
		game->DestroyAsset(body);
		break;
	}
}